// zagSNES
// © MIT ∞ IamRifki

const std = @import("std");
const mem = @import("./memory.zig");
const spc = @import("./spc700.zig");
const ppu = @import("./ppu.zig");

/// Registers
pub const reg = union {
    w: u16,
    b: packed struct {
        l: u8,
        h: u8,
    },
};

const a: reg = undefined;
const x: reg = undefined;
const y: reg = undefined;
const s: reg = undefined;

const pbr: u32 = undefined;
const dbr: u32 = undefined;
const pc: u16 = undefined;
const dp: u16 = undefined;

const p: packed struct {
    c: i16,
    z: i16,
    i: i16,
    d: i16,
    b: i16,
    v: i16,
    n: i16,
    m: i16,
    x: i16,
    e: i16,
} = undefined;

var ins: i16 = undefined;
// var output: i16 = undefined;
// var timeToLive: i16 = undefined;
var inwai: isize = 0;

/// CPU modes :
/// 0 = X1M1
/// 1 = X1M0
/// 2 = X0M1
/// 3 = X0M0
/// 4 = emulation
var cpuMode: i16 = undefined;

/// Current Opcode
var opcode: u8 = undefined;

/// Global Cycles Count
var cycles: i16 = undefined;

/// Temporary Variables
var addr: u32 = undefined;

/// Addressing Modes
fn absolute() u32 {
    var temp: u32 = mem.readMemW(pbr | pc);
    pc += 2;
    return temp | dbr;
}

fn absoluteX() u32 {
    var temp: u32 = (mem.readMemW(pbr | pc)) + x.w + dbr;
    pc += 2;
    return temp;
}

fn absoluteY() u32 {
    var temp: u32 = (mem.readMemW(pbr | pc)) + y.w + dbr;
    pc += 2;
    return temp;
}

fn absoluteLong() u32 {
    var temp: u32 = mem.readMemW(pbr | pc);
    temp |= (mem.readMem(pbr | pc) << 16);
    pc += 2;
    return temp;
}

fn absoluteLongX() u32 {
    var temp: u32 = (mem.readMemW(pbr | pc)) + x.w;
    temp |= (mem.readMem(pbr | pc) << 16);
    pc += 2;
    return temp;
}

fn directPage() u32 {
    var temp: u32 = mem.readMem(pbr | pc);
    pc += 1;
    temp += dp;
    if (dp & 0xFF != 0) {
        cycles -= 6;
        spc.clockSpc(6);
    }
    return temp & 0xFFFF;
}

fn directPageX() u32 {
    var temp: u32 = mem.readMem(pbr | pc) + x.w;
    if (p.e != 0) {
        temp &= 0xFF;
    }
    pc += 1;
    temp += dp;
    if (dp & 0xFF != 0) {
        cycles -= 6;
        spc.clockSpc(6);
    }
    return temp & 0xFFFF;
}

fn directPageY() u32 {
    var temp: u32 = mem.readMem(pbr | pc) + y.w;
    if (p.e != 0) {
        temp &= 0xFF;
    }
    pc += 1;
    temp += dp;
    if (dp & 0xFF != 0) {
        cycles -= 6;
        spc.clockSpc(6);
    }
    return temp & 0xFFFF;
}

fn stack() u32 {
    var temp: u32 = mem.readMem(pbr | pc);
    pc += 1;
    temp += s.w;
    return (mem.readMem(temp)) + dbr;
}

fn indirect() u32 {
    var temp: u32 = (mem.readMem(pbr | pc) + dp) & 0xFFFF;
    pc += 1;
    return (mem.readMemW(temp)) + dbr;
}

fn indirectX() u32 {
    var temp: u32 = (mem.readMem(pbr | pc) + dp + x.w) & 0xFFFF;
    pc += 1;
    return (mem.readMemW(temp)) + dbr;
}

fn jIndirectX() u32 { // *JSR (,x) uses PBR instead of DBR, and 2 byte address insted of 1 + dp
    var temp: u32 = (mem.readMem(pbr | pc) + (mem.readMem((pbr | pc) + 1) << 8) + x.w) + pbr;
    pc += 2;
    return temp;
}

fn indirectY() u32 {
    var temp: u32 = (mem.readMem(pbr | pc) + dp) & 0xFFFF;
    pc += 1;
    return (mem.readMemW(temp)) + y.w + dbr;
}

fn sIndirectY() u32 {
    var temp: u32 = (mem.readMem(pbr | pc) + s.w) & 0xFFFF;
    pc += 1;
    return (mem.readMemW(temp)) + y.w + dbr;
}

fn indirectLong() u32 {
    var temp: u32 = (mem.readMem(pbr | pc) + dp) & 0xFFFF;
    pc += 1;
    var addr: u32 = mem.readMemW(temp) | (mem.readMem(temp + 2) << 16);
    return addr;
}

fn indirectLongY() u32 {
    var temp: u32 = (mem.readMem(pbr | pc) + dp) & 0xFFFF;
    pc += 1;
    var addr: u32 = mem.readMemW(temp) | (mem.readMem(temp + 2) << 16) + y.w;
    return addr;
}

/// Flag Setting
fn setZN8(v) void {
    p.z = if (v == 0) 1 else 0;
    p.n = v & 0x80;
}

fn setZN16(v) void {
    p.z = if (v == 0) 1 else 0;
    p.n = v & 0x8000;
}

/// ADC/SBC functions
fn ADC8() void {
    tempW = a.b.l + temp + if (p.c != 0) 1 else 0;
    p.v = (!((a.b.l ^ temp) & 0x80) & &((a.b.l ^ tempW) & 0x80));
    a.b.l = tempW & 0xFF;
    setZN8(a.b.l);
    p.c = tempW & 0x100;
}

fn ADC16() void {
    tempL = a.w + tempW + if (p.c != 0) 1 else 0;
    p.v = (!((a.w ^ temp) & 0x8000) & &((a.w ^ tempW) & 0x8000));
    a.w = tempW & 0xFFFF;
    setZN16(a.w);
    p.c = tempL & 0x10000;
}

fn ADCBCD8() void {
    tempW = a.b.l & 0xF + temp & 0xF + if (p.c != 0) 1 else 0;
    if (tempW > 9) {
        tempW += 6;
    }
    tempW += (a.b.l & 0xF0) + (temp & 0xF0);
    if (tempW > 0x9F) {
        tempW += 0x60;
    }
    p.v = (!((a.b.l ^ temp) & 0x80) & &((a.b.l ^ tempW) & 0x80));
    a.b.l = tempW & 0xFF;
    setZN8(a.b.l);
    p.c = tempW > 0xFF;
    cycles -= 6;
    spc.clockSpc(6);
}

fn ADCBCD16() void {
    tempL = a.w & 0xF + tempW & 0xF + if (p.c != 0) 1 else 0;
    if (tempL > 9) {
        tempL += 6;
    }
    tempL += a.w & 0xF0 + tempW & 0xF0;
    if (tempL > 0x9F) {
        tempL += 0x60;
    }
    tempL += a.w & 0xF00 + tempW & 0xF00;
    if (tempL > 0x9FF) {
        tempL += 0x600;
    }
    tempL += a.w & 0xF000 + tempW & 0xF000;
    if (tempL > 0x9FFF) {
        tempL += 0x6000;
    }
    p.v = (!((a.w ^ temp) & 0x8000) & &((a.w ^ tempW) & 0x8000));
    a.w = tempW & 0xFFFF;
    setZN16(a.w);
    p.c = tempL > 0xFFFF;
    cycles -= 6;
    spc.clockSpc(6);
}

fn SBC8() void {
    tempW = a.b.l - temp - if (p.c != 0) 0 else 1;
    p.v = ((a.b.l ^ temp) & 0x80) & &((a.b.l ^ tempW) & 0x80);
    a.b.l = tempW & 0xFF;
    setZN8(a.b.l);
    p.c = tempW <= 0xFF;
}

fn SBC16() void {
    tempL = a.w - tempW - if (p.c != 0) 0 else 1;
    p.v = ((a.w ^ tempW) & (a.w ^ tempL)) & 0x8000;
    a.w = tempL & 0xFFFF;
    setZN16(a.w);
    p.c = tempL <= 0xFFFF;
}

fn SBCBCD8() void {
    tempW = a.b.l & 0xF - temp & 0xF - if (p.c != 0) 0 else 1;
    if (tempW > 9) {
        tempW -= 6;
    }
    tempW += (a.b.l & 0xF0) - (temp & 0xF0);
    if (tempW > 0x9F) {
        tempW -= 0x60;
    }
    p.v = ((a.b.l ^ temp) & 0x80) & &((a.b.l ^ tempW) & 0x80);
    a.b.l = tempW & 0xFF;
    setZN8(a.b.l);
    p.c = tempW <= 0xFF;
    cycles -= 6;
    spc.clockSpc(6);
}

fn SBCBCD16() void {
    tempL = a.w & 0xF - tempW & 0xF - if (p.c != 0) 0 else 1;
    if (tempL > 9) {
        tempL -= 6;
    }
    tempL += a.w & 0xF0 - tempW & 0xF0;
    if (tempL > 0x9F) {
        tempL -= 0x60;
    }
    tempL += a.w & 0xF00 - tempW & 0xF00;
    if (tempL > 0x9FF) {
        tempL -= 0x600;
    }
    tempL += a.w & 0xF000 - tempW & 0xF000;
    if (tempL > 0x9FFF) {
        tempL -= 0x6000;
    }
    p.v = ((a.w ^ temp) & 0x8000) & &((a.w ^ tempW) & 0x8000);
    a.w = tempW & 0xFFFF;
    setZN16(a.w);
    p.c = tempL <= 0xFFFF;
    cycles -= 6;
    spc.clockSpc(6);
}

/// Instructions
fn inca8() void {
    mem.readMem(pbc | pc);
    a.b.l += 1;
    setZN8(a.b.l);
}

fn inca16() void {
    mem.readMem(pbc | pc);
    a.w += 1;
    setZN16(a.w);
}

fn inx8() void {
    mem.readMem(pbr | pc);
    x.b.l += 1;
    setZN8(x.b.l);
}

fn inx16() void {
    mem.readMem(pbr | pc);
    x.w += 1;
    setZN16(x.w);
}

fn iny8() void {
    mem.readMem(pbr | pc);
    y.b.l += 1;
    setZN8(y.b.l);
}

fn iny16() void {
    mem.readMem(pbr | pc);
    y.w += 1;
    setZN16(y.w);
}

fn deca8() void {
    mem.readMem(pbr | pc);
    a.b.l -= 1;
    setZN8(a.b.l);
}

fn deca16() void {
    mem.readMem(pbr | pc);
    a.w -= 1;
    setZN16(a.w);
}

fn dex8() void {
    mem.readMem(pbr | pc);
    x.b.l -= 1;
    setZN8(x.b.l);
}

fn dey8() void {
    mem.readMem(pbr | pc);
    y.b.l -= 1;
    setZN8(y.b.l);
}

fn dey16() void {
    mem.readMem(pbr | pc);
    y.w -= 1;
    setZN16(y.w);
}

/// INC Group
fn incZp8() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp += 1;
    setZN16(temp);
    mem.writeMemW(addr, temp);
}

fn incZp16() void {
    var temp: u16 = undefined;
    addr = directPage();
    temp = mem.readMemW(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp += 1;
    setZN16(temp);
    mem.writeMemW(addr, temp);
}

fn incZpX8() void {
    var temp: u8 = undefined;
    addr = directPageX();
    temp = mem.readMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp += 1;
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn incZpX16() void {
    var temp: u16 = undefined;
    addr = directPageX();
    temp = mem.readMemW(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp += 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn incAbs8() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp += 1;
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn incAbs16() void {
    var temp: u16 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp += 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn incAbsX8() void {
    var temp: u8 = undefined;
    addr = absoluteX();
    temp = mem.readMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp += 1;
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn incAbsX16() void {
    var temp: u16 = undefined;
    addr = absoluteX();
    temp = mem.readMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp += 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

/// DEC Group
fn decZp8() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp -= 1;
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn decZp16() void {
    var temp: u16 = undefined;
    addr = directPage();
    temp = mem.readMemW(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp -= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn decZpX8() void {
    var temp: u8 = undefined;
    addr = directPageX();
    temp = mem.readMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp -= 1;
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn decZpX16() void {
    var temp: u16 = undefined;
    addr = directPageX();
    temp = mem.readMemW(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp -= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn decAbs8() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp -= 1;
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn decAbs16() void {
    var temp: u16 = undefined;
    addr = absolute();
    temp = mem.readMemW(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp -= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn decAbsX8() void {
    var temp: u8 = undefined;
    addr = absoluteX();
    temp = mem.readMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp -= 1;
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn decAbsX16() void {
    var temp: u16 = undefined;
    addr = absoluteX();
    temp = mem.readMemW(addr);
    cycles -= 6;
    spc.clockSpc(6);
    temp -= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

/// Flag Group
fn clc() void {
    mem.readMem(pbr | pc);
    p.c = 0;
}

fn cld() void {
    mem.readMem(pbr | pc);
    p.d = 0;
}

fn cli() void {
    mem.readMem(pbr | pc);
    p.i = 0;
}

fn clv() void {
    mem.readMem(pbr | pc);
    p.v = 0;
}

fn sec() void {
    mem.readMem(pbr | pc);
    p.c = 1;
}

fn sed() void {
    mem.readMem(pbr | pc);
    p.d = 1;
}

fn sei() void {
    mem.readMem(pbr | pc);
    p.i = 1;
}

fn xce() void {
    var temp: isize = p.c;
    p.c = p.e;
    p.e = temp;
    mem.readMem(pbr | pc);
    updateCpuMode();
}

fn sep() void {
    var temp: u8 = mem.readMem(pbr | pc);
    pc += 1;
    if (temp & 1 != 0) {
        p.c = 1;
    }
    if (temp & 2 != 0) {
        p.z = 1;
    }
    if (temp & 4 != 0) {
        p.i = 1;
    }
    if (temp & 8 != 0) {
        p.d = 1;
    }
    if (temp & 0x40 != 0) {
        p.v = 1;
    }
    if (temp & 0x80 != 0) {
        p.n = 1;
    }
    if (!p.e) {
        if (temp & 0x10 != 0) {
            p.x = 1;
        }
        if (temp & 0x20 != 0) {
            p.m = 1;
        }
        updateCpuMode();
    }
}

fn rep() void {
    var temp: u8 = mem.readMem(pbr | pc);
    pc += 1;
    if (temp & 1 != 0) {
        p.c = 0;
    }
    if (temp & 2 != 0) {
        p.z = 0;
    }
    if (temp & 4 != 0) {
        p.i = 0;
    }
    if (temp & 8 != 0) {
        p.d = 0;
    }
    if (temp & 0x40 != 0) {
        p.v = 0;
    }
    if (temp & 0x80 != 0) {
        p.n = 0;
    }
    if (p.e == 0) {
        if (temp & 0x00 != 0) {
            p.x = 0;
        }
        if (temp & 0x20 != 0) {
            p.m = 0;
        }
        updateCpuMode();
    }
}

/// Transfer Group
fn tax8() void {
    mem.readMem(pbr | pc);
    x.b.l = a.b.l;
    setZN8(x.b.l);
}

fn tay8() void {
    mem.readMem(pbr | pc);
    y.b.l = a.b.l;
    setZN8(y.b.l);
}

fn txa8() void {
    mem.readMem(pbr | pc);
    a.b.l = x.b.l;
    setZN8(a.b.l);
}

fn tya8() void {
    mem.readMem(pbr | pc);
    a.b.l = y.b.l;
    setZN8(a.b.l);
}

fn tsx8() void {
    mem.readMem(pbr | pc);
    x.b.l = s.b.l;
    setZN8(x.b.l);
}

fn txs8() void {
    mem.readMem(pbr | pc);
    s.b.l = x.b.l;
    // setZN8(x.b.l);
}

fn txy8() void {
    mem.readMem(pbr | pc);
    y.b.l = x.b.l;
    setZN8(y.b.l);
}

fn tax16() void {
    mem.readMem(pbr | pc);
    x.b.l = a.b.l;
    setZN16(x.b.l);
}

fn tay16() void {
    mem.readMem(pbr | pc);
    y.b.l = a.b.l;
    setZN16(y.b.l);
}

fn txa16() void {
    mem.readMem(pbr | pc);
    a.b.l = x.b.l;
    setZN16(a.b.l);
}

fn tya16() void {
    mem.readMem(pbr | pc);
    a.b.l = y.b.l;
    setZN16(a.b.l);
}

fn tsx16() void {
    mem.readMem(pbr | pc);
    x.b.l = s.b.l;
    setZN16(x.b.l);
}

fn txs16() void {
    mem.readMem(pbr | pc);
    s.b.l = x.b.l;
    // setZN16(x.b.l);
}

fn txy16() void {
    mem.readMem(pbr | pc);
    y.b.l = x.b.l;
    setZN16(y.b.l);
}

fn tyx16() void {
    mem.readMem(pbr | pc);
    x.b.l = y.b.l;
    setZN16(x.b.l);
}

/// LDX Group
fn ldxImm8() void {
    x.b.l = mem.readMem(pbr | pc);
    pc += 1;
    setZN8(x.b.l);
}

fn ldxZp8() void {
    addr = directPage();
    x.b.l = mem.readMem(addr);
    setZN8(x.b.l);
}

fn ldxZpy8() void {
    addr = directPageY();
    x.b.l = mem.readMem(addr);
    setZN8(x.b.l);
}

fn ldxAbs8() void {
    addr = absolute();
    x.b.l = mem.readMem(addr);
    setZN8(x.b.l);
}

fn ldxAbsY8() void {
    addr = absoluteY();
    x.b.l = mem.readMem(addr);
    setZN8(x.b.l);
}

fn ldxImm16() void {
    x.w = mem.readMemW(pbr | pc);
    pc += 2;
    setZN16(x.w);
}

fn ldxZp16() void {
    addr = directPage();
    x.w = mem.readMemW(addr);
    setZN16(x.w);
}

fn ldxZpy16() void {
    addr = directPageY();
    x.w = mem.readMem(addr);
    setZN8(x.w);
}

fn ldxAbs16() void {
    addr = absolute();
    x.w = mem.readMem(addr);
    setZN8(x.w);
}

fn ldxAbsY16() void {
    addr = absolute();
    x.w = mem.readMem(addr);
    setZN8(x.w);
}

/// LDY Group
fn ldyImm8() void {
    y.b.l = mem.readMem(pbr | pc);
    pc += 1;
    setZN8(y.b.l);
}

fn ldyZp8() void {
    addr = directPage();
    y.b.l = mem.readMem(addr);
    setZN8(y.b.l);
}

fn ldyZpy8() void {
    addr = directPageY();
    y.b.l = mem.readMem(addr);
    setZN8(y.b.l);
}

fn ldyAbs8() void {
    addr = absolute();
    y.b.l = mem.readMem(addr);
    setZN8(y.b.l);
}

fn ldyAbsY8() void {
    addr = absoluteY();
    y.b.l = mem.readMem(addr);
    setZN8(y.b.l);
}

fn ldyImm16() void {
    y.w = mem.readMemW(pbr | pc);
    pc += 2;
    setZN16(y.w);
}

fn ldyZp16() void {
    addr = directPage();
    y.w = mem.readMemW(addr);
    setZN16(y.w);
}

fn ldyZpy16() void {
    addr = directPageY();
    y.w = mem.readMem(addr);
    setZN8(y.w);
}

fn ldyAbs16() void {
    addr = absolute();
    y.w = mem.readMem(addr);
    setZN8(y.w);
}

fn ldyAbsY16() void {
    addr = absolute();
    y.w = mem.readMem(addr);
    setZN8(y.w);
}

/// LDA Group
fn ldaImm8() void {
    a.b.l = mem.readMem(pbr | pc);
    pc += 1;
    setZN8(a.b.l);
}

fn ldaZp8() void {
    addr = directPage();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaZpX8() void {
    addr = directPageX();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaSp8() void {
    addr = stack();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaSIndirectY8() void {
    addr = sIndirectY();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaAbs8() void {
    addr = absolute();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaAbsX8() void {
    addr = absoluteX();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaAbsY8() void {
    addr = absoluteY();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaLong8() void {
    addr = absoluteLong();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaLongX8() void {
    addr = absoluteLongX();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaIndirect8() void {
    addr = indirect();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaIndirectX8() void {
    addr = indirectX();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaIndirectY8() void {
    addr = indirectY();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaIndirectLong8() void {
    addr = indirectLong();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaIndirectLongY8() void {
    addr = indirectLongY();
    a.b.l = mem.readMem(addr);
    setZN8(a.b.l);
}

fn ldaImm16() void {
    a.w = mem.readMemW(pbr | pc);
    pc += 2;
    setZN16(a.w);
}

fn ldaZp16() void {
    addr = directPage();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ladZpX16() void {
    addr = directPageX();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaSp16() void {
    addr = stack();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaSIndirectY16() void {
    addr = sIndirectY();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaAbs16() void {
    addr = absolute();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaAbsX16() void {
    addr = absoluteX();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaAbsY16() void {
    addr = absoluteY();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaLong16() void {
    addr = absoluteLong();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaLongX16() void {
    addr = absoluteLongX();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaIndirect16() void {
    addr = indirect();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaIndirectX16() void {
    addr = indirectX();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaIndirectY16() void {
    addr = indirectY();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaIndirectLong16() void {
    addr = indirectLong();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

fn ldaIndirectLongY16() void {
    addr = indirectLongY();
    a.w = mem.readMemW(addr);
    setZN16(a.w);
}

/// STA Group
fn staZp8() void {
    addr = directPage();
    mem.writeMem(addr, a.b.l);
}

fn staZpX8() void {
    addr = directPageX();
    mem.writeMem(addr, a.b.l);
}

fn staAbs8() void {
    addr = absolute();
    mem.writeMem(addr, a.b.l);
}

fn staAbsX8() void {
    addr = absoluteX();
    mem.writeMem(addr, a.b.l);
}

fn staAbsY8() void {
    addr = absoluteY();
    mem.writeMem(addr, a.b.l);
}

fn staLong8() void {
    addr = absoluteLong();
    mem.writeMem(addr, a.b.l);
}

fn staLongX8() void {
    addr = absoluteLongX();
    mem.writeMem(addr, a.b.l);
}

fn staIndirect8() void {
    addr = indirect();
    mem.writeMem(addr, a.b.l);
}

fn staIndirectX8() void {
    addr = indirectX();
    mem.writeMem(addr, a.b.l);
}

fn staIndirectY8() void {
    addr = indirectY();
    mem.writeMem(addr, a.b.l);
}

fn staIndirectLongX8() void {
    addr = indirectLongX();
    mem.writeMem(addr, a.b.l);
}

fn staIndirectLongY8() void {
    addr = indirectLongY();
    mem.writeMem(addr, a.b.l);
}

fn staSp8() void {
    addr = stack();
    mem.writeMem(addr, a.b.l);
}

fn staSIndirectY8() void {
    addr = sIndirectY();
    mem.writeMem(addr, a.b.l);
}

fn staZp16() void {
    addr = directPage();
    mem.writeMemW(addr, a.w);
}

fn staZpX16() void {
    addr = directPageX();
    mem.writeMemW(addr, a.w);
}

fn staAbs16() void {
    addr = absolute();
    mem.writeMemW(addr, a.w);
}

fn staAbsX16() void {
    addr = absoluteX();
    mem.writeMemW(addr, a.w);
}

fn staAbsY16() void {
    addr = absoluteY();
    mem.writeMemW(addr, a.w);
}

fn staLong16() void {
    addr = absoluteLong();
    mem.writeMemW(addr, a.w);
}

fn staLongX16() void {
    addr = absoluteLongX();
    mem.writeMemW(addr, a.w);
}

fn staIndirect16() void {
    addr = indirect();
    mem.writeMemW(addr, a.w);
}

fn staIndirectX16() void {
    addr = indirectX();
    mem.writeMemW(addr, a.w);
}

fn staIndirectY16() void {
    addr = indirectY();
    mem.writeMemW(addr, a.w);
}

fn staIndirectLongX16() void {
    addr = indirectLongX();
    mem.writeMemW(addr, a.w);
}

fn staIndirectLongY16() void {
    addr = indirectLongY();
    mem.writeMemW(addr, a.w);
}

fn staSp16() void {
    addr = stack();
    mem.writeMemW(addr, a.w);
}

fn staSIndirectY16() void {
    addr = sIndirectY();
    mem.writeMemW(addr, a.w);
}

/// STX Group
fn stxZp8() void {
    addr = directPage();
    mem.writeMem(addr, x.b.l);
}

fn stxZpY8() void {
    addr = directPageY();
    mem.writeMem(addr, x.b.l);
}

fn stxAbs8() void {
    addr = absolute();
    mem.writeMem(addr, x.b.l);
}

fn stxZp16() void {
    addr = directPage();
    mem.writeMemW(addr, x.w);
}

fn stxZpY16() void {
    addr = directPageY();
    mem.writeMemW(addr, x.w);
}

fn stxAbs16() void {
    addr = absolute();
    mem.writeMemW(addr, x.w);
}

/// STY Group
fn styZp8() void {
    addr = directPage();
    mem.writeMem(addr, y.b.l);
}

fn styZpX8() void {
    addr = directPageX();
    mem.writeMem(addr, y.b.l);
}

fn styAbs8() void {
    addr = absolute();
    mem.writeMem(addr, y.b.l);
}

fn styZp16() void {
    addr = directPage();
    mem.writeMemW(addr, y.w);
}

fn styZpX16() void {
    addr = directPageX();
    mem.writeMemW(addr, y.w);
}

fn styAbs16() void {
    addr = absolute();
    mem.writeMemW(addr, y.w);
}

/// STZ Group
fn stzZp8() void {
    addr = directPage();
    mem.writeMem(addr, 0);
}

fn stzZpX8() void {
    addr = directPageX();
    mem.writeMem(addr, 0);
}

fn stzAbs8() void {
    addr = absolute();
    mem.writeMem(addr, 0);
}

fn stzAbsX8() void {
    addr = absoluteX();
    mem.writeMem(addr, 0);
}

fn stzZp16() void {
    addr = directPage();
    mem.writeMemW(addr, 0);
}

fn stzZpX16() void {
    addr = directPageX();
    mem.writeMemW(addr, 0);
}

fn stzAbs16() void {
    addr = absolute();
    mem.writeMemW(addr, 0);
}

fn stzAbsX16() void {
    addr = absoluteX();
    mem.writeMemW(addr, 0);
}

/// ADC Group
fn adcImm8() void {
    var tempW: u16 = undefined;
    var temp: u8 = mem.readMem(pbr | pc);
    pc += 1;
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcZp8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcZpX8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = directPageX();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcSp8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = stack();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcAbs8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcAbsX8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = absoluteX();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcAbsY8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = absoluteY();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcLong8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = absoluteLong();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcLongX8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = absoluteLongX();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcIndirect8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = indirect();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcIndirectX8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = indirectX();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcIndirectY8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = indirectY();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcsIndirectY8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = sIndirectY();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcIndirectLong8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = indirectLong();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcIndirectLongY8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = indirectLongY();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD8();
    } else {
        ADC8();
    }
}

fn adcImm16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = mem.readMemW(pbr | pc);
    pc += 2;
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcZp16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = directPage();
    tempW = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcZpX16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = directPageX();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcSp16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = stack();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcAbs16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = absolute();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcAbsX16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = absoluteX();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcAbsY16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = absoluteY();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcLong16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = absoluteLong();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcLongX16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = absoluteLongX();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcIndirect16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = indirect();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcIndirectX16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = indirectX();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcIndirectY16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = indirectY();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcsIndirectY16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = sIndirectY();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcIndirectLong16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = indirectLong();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn adcIndirectLongY16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = indirectLongY();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

/// SBC Group
fn sbcImm8() void {
    var tempW: u16 = undefined;
    var temp: u8 = mem.readMem(pbr | pc);
    pc += 1;
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcZp8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcZpX8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = directPageX();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcSp8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = stack();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcAbs8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcAbsX8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = absoluteX();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcAbsY8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = absoluteY();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcLong8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = absoluteLong();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcLongX8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = absoluteLongX();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcIndirect8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = indirect();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcIndirectX8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = indirectX();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcIndirectY8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = indirectY();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcsIndirectY8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = sIndirectY();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcIndirectLong8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = indirectLong();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcIndirectLongY8() void {
    var tempW: u16 = undefined;
    var temp: u8 = undefined;
    addr = indirectLongY();
    temp = mem.readMem(addr);
    if (p.d) {
        SBCBCD8();
    } else {
        SBC8();
    }
}

fn sbcImm16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = mem.readMemW(pbr | pc);
    pc += 2;
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcZp16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = directPage();
    tempW = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcZpX16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = directPageX();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcSp16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = stack();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcAbs16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = absolute();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcAbsX16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = absoluteX();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcAbsY16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = absoluteY();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcLong16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = absoluteLong();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcLongX16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = absoluteLongX();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcIndirect16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = indirect();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcIndirectX16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = indirectX();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcIndirectY16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = indirectY();
    temp = mem.readMemW(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcsIndirectY16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = sIndirectY();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcIndirectLong16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = indirectLong();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

fn sbcIndirectLongY16() void {
    var tempL: u32 = undefined;
    var tempW: u16 = undefined;
    addr = indirectLongY();
    temp = mem.readMem(addr);
    if (p.d) {
        ADCBCD16();
    } else {
        ADC16();
    }
}

/// EOR Group
fn eorImm8() void {
    a.b.l ^= mem.readMem(pbr | pc);
    pc += 1;
    setZN8(a.b.l);
}

fn eorZp8() void {
    addr = directPage();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorZpX8() void {
    addr = directPageX();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorSp8() void {
    addr = stack();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorSIndirectY8() void {
    addr = sIndirectY();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorAbs8() void {
    addr = absolute();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorAbsX8() void {
    addr = absoluteX();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorAbsY8() void {
    addr = absoluteY();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorLong8() void {
    addr = absoluteLong();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorLongX8() void {
    addr = absoluteLongX();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorIndirect8() void {
    addr = indirect();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorIndirectX8() void {
    addr = indirectX();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorIndirectY8() void {
    addr = indirectY();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorIndirectLong8() void {
    addr = indirectLong();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorIndirectLongY8() void {
    addr = indirectLongY();
    a.b.l ^= mem.readMem(addr);
    setZN8(a.b.l);
}

fn eorImm16() void {
    a.w = mem.readMemW(pbr | pc);
    pc += 2;
    setZN16(a.w);
}

fn eorZp16() void {
    addr = directPage();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorZpX16() void {
    addr = directPageX();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorSp16() void {
    addr = stack();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorSIndirectY16() void {
    addr = sIndirectY();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorAbs16() void {
    addr = absolute();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorAbsX16() void {
    addr = absoluteX();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorAbsY16() void {
    addr = absoluteY();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorLong16() void {
    addr = absoluteLong();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorLongX16() void {
    addr = absoluteLongX();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorIndirect16() void {
    addr = indirect();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorIndirectX16() void {
    addr = indirectX();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorIndirectY16() void {
    addr = indirectY();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorIndirectLong16() void {
    addr = indirectLong();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

fn eorIndirectLongY16() void {
    addr = indirectLongY();
    a.w ^= mem.readMemW(addr);
    setZN16(a.w);
}

/// AND Group
fn andImm8() void {
    a.b.l &= mem.readMem(pbr | pc);
    pc += 1;
    setZN8(a.b.l);
}

fn andZp8() void {
    addr = directPage();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andZpX8() void {
    addr = directPageX();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andSp8() void {
    addr = stack();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andSIndirectY8() void {
    addr = sIndirectY();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andAbs8() void {
    addr = absolute();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andAbsX8() void {
    addr = absoluteX();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andAbsY8() void {
    addr = absoluteY();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andLong8() void {
    addr = absoluteLong();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andLongX8() void {
    addr = absoluteLongX();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andIndirect8() void {
    addr = indirect();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andIndirectX8() void {
    addr = indirectX();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andIndirectY8() void {
    addr = indirectY();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andIndirectLong8() void {
    addr = indirectLong();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andIndirectLongY8() void {
    addr = indirectLongY();
    a.b.l &= mem.readMem(addr);
    setZN8(a.b.l);
}

fn andImm16() void {
    a.w = mem.readMemW(pbr | pc);
    pc += 2;
    setZN16(a.w);
}

fn andZp16() void {
    addr = directPage();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andZpX16() void {
    addr = directPageX();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andSp16() void {
    addr = stack();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andSIndirectY16() void {
    addr = sIndirectY();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andAbs16() void {
    addr = absolute();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andAbsX16() void {
    addr = absoluteX();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andAbsY16() void {
    addr = absoluteY();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andLong16() void {
    addr = absoluteLong();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andLongX16() void {
    addr = absoluteLongX();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andIndirect16() void {
    addr = indirect();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andIndirectX16() void {
    addr = indirectX();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andIndirectY16() void {
    addr = indirectY();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andIndirectLong16() void {
    addr = indirectLong();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

fn andIndirectLongY16() void {
    addr = indirectLongY();
    a.w &= mem.readMemW(addr);
    setZN16(a.w);
}

/// ORA Group
fn oraImm8() void {
    a.b.l |= mem.readMem(pbr | pc);
    pc += 1;
    setZN8(a.b.l);
}

fn oraZp8() void {
    addr = directPage();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraZpX8() void {
    addr = directPageX();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraSp8() void {
    addr = stack();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraSIndirectY8() void {
    addr = sIndirectY();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraAbs8() void {
    addr = absolute();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraAbsX8() void {
    addr = absoluteX();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraAbsY8() void {
    addr = absoluteY();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraLong8() void {
    addr = absoluteLong();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraLongX8() void {
    addr = absoluteLongX();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraIndirect8() void {
    addr = indirect();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraIndirectX8() void {
    addr = indirectX();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraIndirectY8() void {
    addr = indirectY();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraIndirectLong8() void {
    addr = indirectLong();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraIndirectLongY8() void {
    addr = indirectLongY();
    a.b.l |= mem.readMem(addr);
    setZN8(a.b.l);
}

fn oraImm16() void {
    a.w = mem.readMemW(pbr | pc);
    pc += 2;
    setZN16(a.w);
}

fn oraZp16() void {
    addr = directPage();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraZpX16() void {
    addr = directPageX();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraSp16() void {
    addr = stack();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraSIndirectY16() void {
    addr = sIndirectY();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraAbs16() void {
    addr = absolute();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraAbsX16() void {
    addr = absoluteX();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraAbsY16() void {
    addr = absoluteY();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraLong16() void {
    addr = absoluteLong();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraLongX16() void {
    addr = absoluteLongX();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraIndirect16() void {
    addr = indirect();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraIndirectX16() void {
    addr = indirectX();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraIndirectY16() void {
    addr = indirectY();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraIndirectLong16() void {
    addr = indirectLong();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

fn oraIndirectLongY16() void {
    addr = indirectLongY();
    a.w |= mem.readMemW(addr);
    setZN16(a.w);
}

/// Bit Group
fn bitImm8() void {
    var temp: u8 = mem.readMem(pbr | pc);
    pc += 1;
    p.z = !(temp & a.b.l);
}

fn bitImm16() void {
    var temp: u16 = mem.readMemW(pbr | pc);
    pc += 2;
    p.z = !(temp & a.w);
    ppu.setZF = 0;
}

fn bitZp8() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    p.z = !(temp & a.b.l);
    p.v = temp & 0x40;
    p.n = temp & 0x80;
}

fn bitZp16() void {
    var temp: u16 = undefined;
    addr = directPage();
    temp = mem.readMemW(addr);
    p.z = !(temp & a.w);
    p.v = temp & 0x4000;
    p.n = temp & 0x8000;
}

fn bitZpX8() void {
    var temp: u8 = undefined;
    addr = directPageX();
    temp = mem.readMem(addr);
    p.z = !(temp & a.b.l);
    p.v = temp & 0x40;
    p.n = temp & 0x80;
}

fn bitZpX16() void {
    var temp: u16 = undefined;
    addr = directPageX();
    temp = mem.readMemW(addr);
    p.z = !(temp & a.w);
    p.v = temp & 0x4000;
    p.n = temp & 0x8000;
}

fn bitAbs8() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    p.z = !(temp & a.b.l);
    p.v = temp & 0x40;
    p.n = temp & 0x80;
}

fn bitAbs16() void {
    var temp: u16 = undefined;
    addr = absolute();
    temp = mem.readMemW(addr);
    p.z = !(temp & a.w);
    p.v = temp & 0x4000;
    p.n = temp & 0x8000;
}

fn bitAbsX8() void {
    var temp: u8 = undefined;
    addr = absoluteX();
    temp = mem.readMem(addr);
    p.z = !(temp & a.b.l);
    p.v = temp & 0x40;
    p.n = temp & 0x80;
}

fn bitAbsX16() void {
    var temp: u16 = undefined;
    addr = absoluteX();
    temp = mem.readMemW(addr);
    p.z = !(temp & a.w);
    p.v = temp & 0x4000;
    p.n = temp & 0x8000;
}

/// CMP Group
fn cmpImm8() void {
    var temp: u8 = undefined;
    temp = mem.readMem(pbr | pc);
    pc += 1;
    setZN8(a.b.l - temp);
    p.c = (a.b.l >= temp);
}

fn cmpZp8() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpZpX8() void {
    var temp: u8 = undefined;
    addr = directPageX();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpSp8() void {
    var temp: u8 = undefined;
    addr = stack();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpAbs8() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpAbsX8() void {
    var temp: u8 = undefined;
    addr = absoluteX();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpAbsY8() void {
    var temp: u8 = undefined;
    addr = absoluteY();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpLong8() void {
    var temp: u8 = undefined;
    addr = absoluteLong();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpLongX8() void {
    var temp: u8 = undefined;
    addr = absoluteLongX();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpIndirect8() void {
    var temp: u8 = undefined;
    addr = indirect();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpIndirectX8() void {
    var temp: u8 = undefined;
    addr = indirectX();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpIndirectY8() void {
    var temp: u8 = undefined;
    addr = indirectY();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpIndirectLong8() void {
    var temp: u8 = undefined;
    addr = indirectL();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpIndirectLongY8() void {
    var temp: u8 = undefined;
    addr = indirectLY();
    temp = mem.readMem(addr);
    setZN8(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpImm16() void {
    var temp: u16 = undefined;
    temp = mem.readMemW(pbr | pc);
    pc += 1;
    setZN16(a.b.l - temp);
    p.c = (a.b.l >= temp);
}

fn cmpZp16() void {
    var temp: u16 = undefined;
    addr = directPage();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpZpX16() void {
    var temp: u16 = undefined;
    addr = directPageX();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpSp16() void {
    var temp: u16 = undefined;
    addr = stack();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpAbs16() void {
    var temp: u16 = undefined;
    addr = absolute();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpAbsX16() void {
    var temp: u16 = undefined;
    addr = absoluteX();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpAbsY16() void {
    var temp: u16 = undefined;
    addr = absoluteY();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpLong16() void {
    var temp: u16 = undefined;
    addr = absoluteLong();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpLongX16() void {
    var temp: u16 = undefined;
    addr = absoluteLongX();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpIndirect16() void {
    var temp: u16 = undefined;
    addr = indirect();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpIndirectX16() void {
    var temp: u16 = undefined;
    addr = indirectX();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpIndirectY16() void {
    var temp: u16 = undefined;
    addr = indirectY();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpIndirectLong16() void {
    var temp: u16 = undefined;
    addr = indirectL();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

fn cmpIndirectLongY16() void {
    var temp: u16 = undefined;
    addr = indirectLY();
    temp = mem.readMemW(addr);
    setZN16(a.b.l - temp);
    p.c = a.b.l >= temp;
}

/// Stack Group
fn phb() void {
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, dbr >> 16);
    s.w -= 1;
}

fn phbe() void {
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, dbr >> 16);
    s.b.l -= 1;
}

fn phk() void {
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, pbr >> 16);
    s.w -= 1;
}

fn phke() void {
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, pbr >> 16);
    s.b.l -= 1;
}

fn pea() void {
    addr = mem.readMemW(pbr | pc);
    pc += 2;
    mem.writeMem(s.w, addr >> 8);
    s.w -= 1;
    mem.writeMem(s.w, addr & 0xFF);
    s.w -= 1;
}

fn pei() void {
    addr = indirect();
    mem.writeMem(s.w, addr >> 8);
    s.w -= 1;
    mem.writeMem(s.w, addr & 0xFF);
    s.w -= 1;
}

fn per() void {
    addr = mem.readMemW(pbr | pc);
    pc + 2;
    addr += pc;
    mem.writeMem(s.w, addr >> 8);
    s.w -= 1;
    mem.writeMem(s.w, addr & 0xFF);
    s.w -= 1;
}

fn phd() void {
    mem.writeMem(s.w, dp >> 8);
    s.w -= 1;
    mem.writeMem(s.w, dp & 0xFF);
    s.w -= 1;
}

fn pld() void {
    mem.readMem(pbr | pc);
    s.w += 1;
    cycles -= 6;
    spc.clockSpc(6);
    dp = mem.readMem(s.w);
    s.w += 1;
    dp |= mem.readMem(s.w) << 8;
}

fn pha8() void {
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, a.b.l);
    s.w -= 1;
}

fn pha16() void {
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, a.b.h);
    s.w -= 1;
    mem.writeMem(s.w, a.b.l);
    s.w -= 1;
}

fn phx8() void {
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, x.b.l);
    s.w -= 1;
}

fn phx16() void {
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, x.b.h);
    s.w -= 1;
    mem.writeMem(s.w, x.b.l);
    s.w -= 1;
}

fn phy8() void {
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, y.b.l);
    s.w -= 1;
}

fn phy16() void {
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, y.b.h);
    s.w -= 1;
    mem.writeMem(s.w, y.b.l);
    s.w -= 1;
}

fn pla8() void {
    mem.readMem(pbr | pc);
    s.w += 1;
    cycles -= 6;
    spc.clockSpc(6);
    a.b.l = mem.readMem(s.w);
    setZN8(a.b.l);
}

fn pla16() void {
    mem.readMem(pbr | pc);
    s.w += 1;
    cycles -= 6;
    spc.clockSpc(6);
    a.b.l = mem.readMem(s.w);
    s.w += 1;
    a.b.h = mem.readMem(s.w);
    setZN16(a.w);
}

fn plx8() void {
    mem.readMem(pbr | pc);
    s.w += 1;
    cycles -= 6;
    spc.clockSpc(6);
    x.b.l = mem.readMem(s.w);
    setZN8(x.b.l);
}

fn plx16() void {
    mem.readMem(pbr | pc);
    s.w += 1;
    cycles -= 6;
    spc.clockSpc(6);
    x.b.l = mem.readMem(s.w);
    s.w += 1;
    x.b.h = mem.readMem(s.w);
    setZN16(x.w);
}

fn ply8() void {
    mem.readMem(pbr | pc);
    s.w += 1;
    cycles -= 6;
    spc.clockSpc(6);
    y.b.l = mem.readMem(s.w);
    setZN8(y.b.l);
}

fn ply16() void {
    mem.readMem(pbr | pc);
    s.w += 1;
    cycles -= 6;
    spc.clockSpc(6);
    y.b.l = mem.readMem(s.w);
    s.w += 1;
    y.b.h = mem.readMem(s.w);
    setZN16(y.w);
}

fn plb() void {
    mem.readMem(pbr | pc);
    s.w += 1;
    cycles -= 6;
    clockSpc(6);
    dbr = mem.readMem(s.w) << 16;
}

fn plbe() void {
    mem.readMem(pbr | pc);
    s.b.l += 1;
    cycles -= 6;
    clockSpc(6);
    dbr = mem.readMem(s.w) << 16;
}

fn plp() void {
    var temp: u8 = mem.readMem(s.w + 1);
    s.w += 1;
    p.c = temp & 1;
    p.z = temp & 2;
    p.i = temp & 4;
    p.d = temp & 8;
    p.x = temp & 0x10;
    p.m = temp & 0x20;
    p.v = temp & 0x40;
    p.n = temp & 0x80;
    cycles -= 12;
    clockSpc(12);
    updateCpuMode();
}

fn plpe() void {
    var temp: u8 = undefined;
    s.b.l += 1;
    temp = mem.readMem(s.w);
    p.c = temp & 1;
    p.z = temp & 2;
    p.i = temp & 4;
    p.d = temp & 8;
    p.v = temp & 0x40;
    p.n = temp & 0x80;
    cycles -= 12;
    clockSpc(12);
}

fn php() void {
    var temp = if (p.c) 1 else 0;
    if (p.z) {
        temp |= 2;
    }
    if (p.i) {
        temp |= 4;
    }
    if (p.d) {
        temp |= 8;
    }
    if (p.x) {
        temp |= 0x10;
    }
    if (p.m) {
        temp |= 0x20;
    }
    if (p.v) {
        temp |= 0x40;
    }
    if (p.n) {
        temp |= 0x80;
    }
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, temp);
    s.w -= 1;
}

fn phpe() void {
    var temp = if (p.c) 1 else 0;
    if (p.z) {
        temp |= 2;
    }
    if (p.i) {
        temp |= 4;
    }
    if (p.d) {
        temp |= 8;
    }
    if (p.v) {
        temp |= 0x40;
    }
    if (p.n) {
        temp |= 0x80;
    }
    temp |= 0x80;
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, temp);
    s.b.l -= 1;
}

/// CPX Group
fn cpxImm8() void {
    var temp: u8 = mem.readMem(pbr | pc);
    pc += 1;
    setZN8(x.b.l - temp);
    p.c = (x.b.l >= temp);
}

fn cpxImm16() void {
    var temp: u16 = mem.readMemW(pbr | pc);
    pc += 2;
    setZN8(x.w - temp);
    p.c = (x.w >= temp);
}

fn cpxZp8() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    setZN8(x.b.l - temp);
    p.c = (x.b.l >= temp);
}

fn cpxZp16() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMemW(addr);
    setZN16(x.w - temp);
    p.c = (x.w >= temp);
}

fn cpxAbs8() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    setZN8(x.b.l - temp);
    p.c = (x.b.l >= temp);
}

fn cpxAbs16() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMemW(addr);
    setZN16(x.w - temp);
    p.c = (x.w >= temp);
}

/// CPY Group
fn cpyImm8() void {
    var temp: u8 = mem.readMem(pbr | pc);
    pc += 1;
    setZN8(y.b.l - temp);
    p.c = (y.b.l >= temp);
}

fn cpyImm16() void {
    var temp: u16 = mem.readMemW(pbr | pc);
    pc += 2;
    setZN8(y.w - temp);
    p.c = (y.w >= temp);
}

fn cpyZp8() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    setZN8(y.b.l - temp);
    p.c = (y.b.l >= temp);
}

fn cpyZp16() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMemW(addr);
    setZN16(y.w - temp);
    p.c = (y.w >= temp);
}

fn cpyAbs8() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    setZN8(y.b.l - temp);
    p.c = (y.b.l >= temp);
}

fn cpyAbs16() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMemW(addr);
    setZN16(y.w - temp);
    p.c = (y.w >= temp);
}

/// Branch Group
fn bcc() void {
    var temp: u8 = @truncate(u8, mem.readMem(pbr | pc));
    pc += 1;
    if (!p.c) {
        pc += temp;
        cycles -= 6;
        clockSpc(6);
    }
}

fn bcs() void {
    var temp: u8 = @truncate(u8, mem.readMem(pbr | pc));
    pc += 1;
    if (p.c) {
        pc += temp;
        cycles -= 6;
        clockSpc(6);
    }
}

fn beq() void {
    var temp: u8 = @truncate(u8, mem.readMem(pbr | pc));
    pc += 1;
    if (ppu.setZF > 0) {
        p.z = 0;
    }
    if (ppu.setZF < 0) {
        p.z = 1;
    }
    ppu.setZF = 0;
    if (p.z) {
        pc += temp;
        cycles -= 6;
        clockSpc(6);
    }
}

fn bne() void {
    var temp: u8 = @truncate(u8, mem.readMem(pbr | pc));
    pc += 1;
    if (ppu.setZF > 0) {
        p.z = 1;
    }
    if (ppu.setZF < 0) {
        p.z = 0;
    }
    setZF = 0;
    if (!p.z) {
        pc += temp;
        cycles -= 6;
        spc.clockSpc(6);
    }
    ppu.skipZ = 0;
}

fn bpl() void {
    var temp: u8 = @truncate(u8, mem.readMem(pbr | pc));
    pc += 1;
    if (!p.n) {
        pc += temp;
        cycles -= 6;
        spc.clockSpc(6);
    }
}

fn bmi() void {
    var temp: u8 = @truncate(u8, mem.readMem(pbr | pc));
    pc += 1;
    if (p.n) {
        pc += temp;
        cycles -= 6;
        spc.clockSpc(6);
    }
}

fn bvc() void {
    var temp: u8 = @truncate(u8, mem.readMem(pbr | pc));
    pc += 1;
    if (!p.v) {
        pc += temp;
        cycles -= 6;
        spc.clockSpc(6);
    }
}

fn bvs() void {
    var temp: u8 = @truncate(u8, mem.readMem(pbr | pc));
    pc += 1;
    if (p.v) {
        pc += temp;
        cycles -= 6;
        spc.clockSpc(6);
    }
}

fn bra() void {
    var temp: u8 = @truncate(u8, mem.readMem(pbr | pc));
    pc += 1;
    pc += temp;
    cycles -= 6;
    spc.clockSpc(6);
}

fn brl() void {
    var temp: u16 = mem.readMemW(pbr | pc);
    pc += 2;
    pc += temp;
    cycles -= 6;
    spc.clockSpc(6);
}

/// Jump Group
fn jmp() void {
    addr = mem.readMemW(pbr | pc);
    pc = addr;
}

fn jmpLong() void {
    addr = mem.readMemW(pbr | pc) | mem.readMem((pbr | pc) + 2) << 16;
    pc = addr & 0xFFFF;
    pbr = addr & 0xFF0000;
}

fn jmpInd() void {
    addr = mem.readMemW(pbr | pc);
    pc = mem.readMemW(addr);
}

fn jmpIndX() void {
    addr = mem.readMemW(pbr | pc) + x.w + pbr;
    pc = mem.readMemW(addr);
}

fn jmlInd() void {
    addr = mem.readMemW(pbr | pc);
    pc = mem.readMemW(addr);
    pbr = mem.readMem(addr + 2) << 16;
}

fn jsr() void {
    addr = mem.readMemW(pbr | pc);
    pc += 1;
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, pc >> 8);
    s.w -= 1;
    mem.writeMem(s.w, pc & 0xFF);
    s.w -= 1;
    pc = addr;
}

fn jsrE() void {
    addr = mem.readMemW(pbr | pc);
    pc += 1;
    mem.readMem(pbr | pc);
    mem.writeMem(s.w, pc >> 8);
    s.b.l -= 1;
    mem.writeMem(s.w, pc & 0xFF);
    s.b.l -= 1;
    pc = addr;
}

fn jsrIndX() void {
    addr = jIndirectX();
    pc -= 1;
    mem.writeMem(s.w, pc >> 8);
    s.w -= 1;
    mem.writeMem(s.w, pc & 0xFF);
    s.w -= 1;
    pc = mem.readMemW(addr);
}

fn jsrIndXE() void {
    addr = jIndirectX();
    pc -= 1;
    mem.writeMem(s.w, pc >> 8);
    s.b.l -= 1;
    mem.writeMem(s.w, pc & 0xFF);
    s.b.l -= 1;
    pc = mem.readMemW(addr);
}

fn jsl() void {
    var temp: u8 = undefined;
    addr = mem.readMemW(pbr | pc);
    pc += 2;
    temp = mem.readMem(pbr | pc);
    mem.writeMem(s.w, pbr >> 16);
    s.w -= 1;
    mem.writeMem(s.w, pc >> 8);
    s.w -= 1;
    mem.writeMem(s.w, pc & 0xFF);
    s.w -= 1;
    pc = addr;
    pbr = temp << 16;
}

fn jslE() void {
    var temp: u8 = undefined;
    addr = mem.readMemW(pbr | pc);
    pc += 2;
    temp = mem.readMem(pbr | pc);
    mem.writeMem(s.w, pbr >> 16);
    s.b.l -= 1;
    mem.writeMem(s.w, pc >> 8);
    s.b.l -= 1;
    mem.writeMem(s.w, pc & 0xFF);
    s.b.l -= 1;
    pc = addr;
    pbr = temp << 16;
}

fn rtl() void {
    cycles -= 18;
    spc.clockSpc(18);
    pc = mem.readMemW(s.w + 1);
    s.w += 2;
    pbr = mem.readMemW(s.w + 1) << 16;
    s.w += 1;
    pc += 1;
}

fn rtlE() void {
    cycles -= 18;
    spc.clockSpc(18);
    s.b.l += 1;
    pc = mem.readMem(s.w);
    s.b.l += 1;
    pc |= mem.readMem(s.w) << 8;
    s.b.l += 1;
    pbr = mem.readMem(s.w) << 16;
}

fn rts() void {
    cycles -= 18;
    spc.clockSpc(18);
    pc = mem.readMemW(s.w + 1);
    s.w += 2;
    pc += 1;
}

fn rtsE() void {
    cycles -= 18;
    spc.clockSpc(18);
    s.b.l += 1;
    pc = mem.readMem(s.w);
    s.b.l += 1;
    pc |= mem.readMem(s.w) << 8;
}

fn rti() void {
    var temp: u8 = undefined;
    s.w += 1;
    spc.clockSpc(6);
    temp = mem.readMem(s.w);

    p.c = temp & 1;
    p.z = temp & 2;
    p.i = temp & 4;
    p.d = temp & 8;
    p.x = temp & 0x10;
    p.m = temp & 0x20;
    p.v = temp & 0x40;
    p.n = temp & 0x80;
    s.w += 1;
    pc = mem.readMem(s.w);
    s.w += 1;
    pc |= mem.readMem(s.w) << 8;
    s.w += 1;
    pbr - mem.readMem(s.w) << 16;
    updateCpuMode();
}

/// Shift Group
fn asla8() void {
    mem.readMem(pbr | pc);
    p.c = a.b.l & 0x80;
    a.b.l <<= 1;
    setZN8(a.b.l);
}

fn asla16() void {
    mem.readMem(pbr | pc);
    p.c = a.w & 0x8000;
    a.b.l <<= 1;
    setZN16(a.b.l);
}

fn aslZp8() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 0x80;
    temp <<= 1;
    setZn(temp);
    mem.writeMem(addr, temp);
}

fn aslZp16() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 0x8000;
    temp <<= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn aslZpX8() void {
    var temp: u8 = undefined;
    addr = directPageX();
    temp = mem.readMem(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 0x80;
    temp <<= 1;
    setZn(temp);
    mem.writeMem(addr, temp);
}

fn aslZpX16() void {
    var temp: u8 = undefined;
    addr = directPageX();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 0x8000;
    temp <<= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn aslAbs8() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 0x80;
    temp <<= 1;
    setZn(temp);
    mem.writeMem(addr, temp);
}

fn aslAbs16() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 0x8000;
    temp <<= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn aslAbsX8() void {
    var temp: u8 = undefined;
    addr = absoluteX();
    temp = mem.readMem(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 0x80;
    temp <<= 1;
    setZn(temp);
    mem.writeMem(addr, temp);
}

fn aslAbsX16() void {
    var temp: u8 = undefined;
    addr = absoluteX();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 0x8000;
    temp <<= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn lsra8() void {
    mem.readMem(pbr | pc);
    p.c = a.b.l & 1;
    a.b.l >>= 1;
    setZN8(a.b.l);
}

fn lsra16() void {
    mem.readMem(pbr | pc);
    p.c = a.w & 1;
    a.w >>= 1;
    setZN8(a.w);
}

fn lsrZp8() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 1;
    temp >>= 1;
    setZn(temp);
    mem.writeMem(addr, temp);
}

fn lsrZp16() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 1;
    temp >>= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn lsrZpX8() void {
    var temp: u8 = undefined;
    addr = directPageX();
    temp = mem.readMem(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 1;
    temp >>= 1;
    setZn(temp);
    mem.writeMem(addr, temp);
}

fn lsrZpX16() void {
    var temp: u8 = undefined;
    addr = directPageX();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 1;
    temp >>= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn lsrAbs8() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 1;
    temp >>= 1;
    setZn(temp);
    mem.writeMem(addr, temp);
}

fn lsrAbs16() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 1;
    temp >>= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn lsrAbsX8() void {
    var temp: u8 = undefined;
    addr = absoluteX();
    temp = mem.readMem(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 1;
    temp >>= 1;
    setZn(temp);
    mem.writeMem(addr, temp);
}

fn lsrAbsX16() void {
    var temp: u8 = undefined;
    addr = absoluteX();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    p.c = temp & 1;
    temp >>= 1;
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn rola8() void {
    mem.readMem(pbr | pc);
    addr = p.c;
    p.c = a.b.l & 0x80;
    a.b.l <<= 1;
    if (addr) {
        a.b.l |= 1;
    }
    setZN8(a.b.l);
}

fn rola16() void {
    mem.readMem(pbr | pc);
    addr = p.c;
    p.c = a.w & 0x80;
    a.w <<= 1;
    if (addr) {
        a.w |= 1;
    }
    setZN8(a.w);
}

fn rolZp8() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = directPage();
    temp = mem.ReadMem(addr);
    cycles -= 6;
    clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x80;
    temp <<= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn rolZp16() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = directPage();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x8000;
    temp <<= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn rolZpX8() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = directPageX();
    temp = mem.ReadMem(addr);
    cycles -= 6;
    clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x80;
    temp <<= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn rolZpX16() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = directPageX();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x8000;
    temp <<= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn rolAbs8() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = absolute();
    temp = mem.ReadMem(addr);
    cycles -= 6;
    clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x80;
    temp <<= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn rolAbs16() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = absolute();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x8000;
    temp <<= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn rolAbsX8() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = absoluteX();
    temp = mem.ReadMem(addr);
    cycles -= 6;
    clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x80;
    temp <<= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn rolAbsX16() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = absoluteX();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x8000;
    temp <<= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn rora8() void {
    mem.readMem(pbr | pc);
    addr = p.c;
    p.c = a.b.l & 0x80;
    a.b.l >>= 1;
    if (addr) {
        a.b.l |= 1;
    }
    setZN8(a.b.l);
}

fn rora16() void {
    mem.readMem(pbr | pc);
    addr = p.c;
    p.c = a.w & 0x80;
    a.w >>= 1;
    if (addr) {
        a.w |= 1;
    }
    setZN8(a.w);
}

fn rorZp8() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = directPage();
    temp = mem.ReadMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x80;
    temp >>= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn rorZp16() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = directPage();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    spc.clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x8000;
    temp >>= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn rorZpX8() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = directPageX();
    temp = mem.ReadMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x80;
    temp >>= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn rorZpX16() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = directPageX();
    temp = mem.ReadMemW(addr);
    cycles -= 6;
    spc.clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x8000;
    temp >>= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn rorAbs8() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = absolute();
    temp = mem.ReadMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x80;
    temp >>= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn rorAbs16() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = absolute();
    temp = mem.readMemW(addr);
    cycles -= 6;
    spc.clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x8000;
    temp >>= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

fn rorAbsX8() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = absoluteX();
    temp = mem.readMem(addr);
    cycles -= 6;
    spc.clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x80;
    temp >>= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN8(temp);
    mem.writeMem(addr, temp);
}

fn rorAbsX16() void {
    var temp: u8 = undefined;
    var tempC: isize = undefined;
    addr = absoluteX();
    temp = mem.readMemW(addr);
    cycles -= 6;
    spc.clockSpc(6);
    tempC = p.c;
    p.c = temp & 0x8000;
    temp >>= 1;
    if (tempC) {
        temp |= 1;
    }
    setZN16(temp);
    mem.writeMemW2(addr, temp);
}

/// Misc Group
fn xba() void {
    mem.readMem(pbr | pc);
    a.w = a.w >> 8 | a.w << 8;
    setZN8(a.b.l);
}

fn nop() void {
    cycles -= 6;
    spc.clockSpc(6);
}

fn tcd() void {
    mem.readMem(pbr | pc);
    dp = a.w;
    setZn16(dp);
}

fn tdc() void {
    mem.readMem(pbr | pc);
    a.w = dp;
    setZn16(a.w);
}

fn tcs() void {
    mem.readMem(pbr | pc);
    s.w = a.w;
    //setZN16(s.w);
}

fn tsc() void {
    mem.readMem(pbr | oc);
    a.w = s.w;
    setZN16(a.w);
}

fn trbZp8() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    p.z!(a.b.l & temp);
    temp &= ~a.b.l;
    cycles -= 6;
    spc.clockSpc(6);
    mem.writeMem(addr, temp);
}

fn trbZp16() void {
    var temp: u16 = undefined;
    addr = directPage();
    temp = mem.readMemW(addr);
    p.z!(a.w & temp);
    temp &= ~a.w;
    cycles -= 6;
    spc.clockSpc(6);
    mem.writeMemW2(addr, temp);
}

fn trbAbs8() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    p.z!(a.b.l & temp);
    temp &= ~a.b.l;
    cycles -= 6;
    spc.clockSpc(6);
    mem.writeMem(addr, temp);
}

fn trbAbs16() void {
    var temp: u16 = undefined;
    addr = absolute();
    temp = mem.readMemW(addr);
    p.z!(a.w & temp);
    temp &= ~a.w;
    cycles -= 6;
    spc.clockSpc(6);
    mem.writeMemW2(addr, temp);
}

fn trbZp8() void {
    var temp: u8 = undefined;
    addr = directPage();
    temp = mem.readMem(addr);
    p.z!(a.b.l & temp);
    temp &= ~a.b.l;
    cycles -= 6;
    spc.clockSpc(6);
    mem.writeMem(addr, temp);
}

fn tsbZp16() void {
    var temp: u16 = undefined;
    addr = directPage();
    temp = mem.readMemW(addr);
    p.z!(a.w & temp);
    temp &= ~a.w;
    cycles -= 6;
    spc.clockSpc(6);
    mem.writeMemW2(addr, temp);
}

fn tsbAbs8() void {
    var temp: u8 = undefined;
    addr = absolute();
    temp = mem.readMem(addr);
    p.z!(a.b.l & temp);
    temp &= ~a.b.l;
    cycles -= 6;
    spc.clockSpc(6);
    mem.writeMem(addr, temp);
}

fn tsbAbs16() void {
    var temp: u16 = undefined;
    addr = absolute();
    temp = readMemW(addr);
    p.z!(a.w & temp);
    temp &= ~a.w;
    cycles -= 6;
    spc.clockSpc(6);
    mem.writeMemW2(addr, temp);
}

fn wai() void {
    mem.readMem(pbr | pc);
    inwai = 1;
    pc -= 1;
}

fn mvp() void {
    var temp: u8 = undefined;
    dbr = mem.readMem(pbr | pc) << 16;
    pc += 1;
    addr = mem.readMem(pbr | pc) << 16;
    pc += 1;
    temp = mem.readMem(addr | x.w);
    mem.writeMem(adr | y.w, temp);
    x.w -= 1;
    y.w -= 1;
    a.w -= 1;
    if (a.w != 0xFFFF) {
        pc -= 3;
    }
    cycles -= 12;
    spc.clockSpc(12);
}

fn mvn() void {
    var temp: u8 = undefined;
    dbr = mem.readMem(pbr | pc) << 16;
    pc += 1;
    addr = mem.readMem(pbr | pc) << 16;
    pc += 1;
    temp = mem.readMem(addr | x.w);
    mem.writeMem(adr | y.w, temp);
    x.w += 1;
    y.w += 1;
    a.w -= 1;
    if (a.w != 0xFFFF) {
        pc -= 3;
    }
    cycles -= 12;
    spc.clockSpc(12);
}

fn brk() void {
    var temp: u8 = undefined;
    mem.writeMem(s.w, pbr >> 16);
    s.w -= 1;
    mem.writeMem(s.w, pc >> 8);
    s.w -= 1;
    mem.writeMem(s.w, pc & 0xFF);
    s.w -= 1;
    if (p.c) {
        temp |= 1;
    }
    if (p.z) {
        temp |= 2;
    }
    if (p.i) {
        temp |= 4;
    }
    if (p.d) {
        temp |= 8;
    }
    if (p.x) {
        temp |= 0x10;
    }
    if (p.m) {
        temp |= 0x20;
    }
    if (p.v) {
        temp |= 0x40;
    }
    if (p.n) {
        temp |= 0x80;
    }
    mem.writeMem(s.w, temp);
    s.w -= 1;
    pc = mem.readMemW(0xFFE6);
    pbr = 0;
    p.i = 1;
    p.d = 0;
}

/// Functions
fn reset65c816() void {
    pbr = 0;
    dbr = 0;
    s.w = 0x1FF;
    cpuMode = 4;
    p.e = 1;
    p.i = 1;
    pc = mem.readMemW(0xFFFC);
    a.w = 0;
    x.w = 0;
    y.w = 0;
    p.x = 1;
    p.m = 1;
    ppu.skipZ = 0;
}

fn badOpcode() void {
    std.debug.warn("Bad opcode {}\n", opcode);
    pc -= 1;
    std.process.exit(0);
}

fn setOpcodes(val: opcode, index: u8, positions: ...) void {
    for (position) |positions| {
        opcodes[index][positions] = val;
    }
}

fn makeOpcodeTable() void {
    // LDA group
    setOpcodes(ldaImm8, 0xA9, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaImm16, 0xA9, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaZp8, 0xA5, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaZp16, 0xA5, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaZpX8, 0xB5, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaZpX16, 0xB5, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaSp8, 0xA3, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaSp16, 0xA3, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaSIndirectY8, 0xB3, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaSIndirectY16, 0xB3, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaAbs8, 0xAD, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaAbs16, 0xAD, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaAbsX8, 0xBD, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaAbsX16, 0xBD, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaAbsY8, 0xB9, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaAbsY16, 0xB9, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaLong8, 0xAF, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaLong16, 0xAF, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaLongX8, 0xBF, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaLongX8, 0xBF, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaIndirect8, 0xB2, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaIndirect16, 0xB2, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaIndirectX8, 0xA1, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaIndirectX16, 0xA1, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaIndirectX8, 0xB1, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaIndirectY16, 0xB1, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaIndirectLong8, 0xA7, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaIndirectLong16, 0xA7, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(ldaIndirectLongY8, 0xB7, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(ldaIndirectLongY16, 0xB7, badOpcode, 1, badOpcode, 3, badOpcode);
    // LDX group
    setOpcodes(ldxImm8, 0xA2, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(ldxImm16, 0xA2, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(ldxZp8, 0xA6, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(ldxZp16, 0xA6, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(ldxZpY8, 0xB6, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(ldxZpY16, 0xB6, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(ldxAbs8, 0xAE, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(ldxAbs16, 0xAE, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(ldxAbsY8, 0xBE, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(ldxAbsY16, 0xBE, badOpcode, badOpcode, 2, 3, badOpcode);
    // LDY group
    setOpcodes(ldyImm8, 0xA0, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(ldyImm16, 0xA0, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(ldyZp8, 0xA4, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(ldyZp16, 0xA4, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(ldyZpY8, 0xB4, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(ldyZpY16, 0xB4, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(ldyAbs8, 0xAC, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(ldyAbs16, 0xAC, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(ldyAbsY8, 0xBC, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(ldyAbsY16, 0xBC, badOpcode, badOpcode, 2, 3, badOpcode);

    // STA group
    setOpcodes(staZp8, 0x85, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staZp16, 0x85, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staZpX8, 0x95, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staZpX16, 0x95, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staAbs8, 0x8D, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staAbs16, 0x8D, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staAbsX8, 0x9D, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staAbsX16, 0x9D, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staAbsY8, 0x99, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staAbsY16, 0x99, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staLong8, 0x8F, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staLong16, 0x8F, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staLongX8, 0x9F, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staLongX16, 0x9F, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staIndirect8, 0x92, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staIndirect16, 0x92, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staIndirectX8, 0x81, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staIndirectX16, 0x81, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staIndirectY8, 0x91, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staIndirectY16, 0x91, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staIndirectLong8, 0x87, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staIndirectLong16, 0x87, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staIndirectLongY8, 0x97, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staIndirectLongY16, 0x97, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staSp8, 0x83, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staSp16, 0x83, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(staSIndirectY8, 0x93, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(staSIndirectY16, 0x93, badOpcode, 1, badOpcode, 3, badOpcode);
    // STX group
    setOpcodes(stxZp8, 0x86, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(stxZp16, 0x86, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(stxZpY8, 0x96, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(stxZpY16, 0x96, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(stxAbs8, 0x8E, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(stxAbs16, 0x8E, badOpcode, badOpcode, 2, 3, badOpcode);
    // STY group
    setOpcodes(styZp8, 0x84, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(styZp16, 0x84, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(styZpX8, 0x94, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(styZpX16, 0x94, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(styAbs8, 0x8C, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(styAbs16, 0x8C, badOpcode, badOpcode, 2, 3, badOpcode);
    // STZ group
    setOpcodes(stzZp8, 0x64, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(stzZp16, 0x64, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(stzZpX8, 0x74, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(stzZpX16, 0x74, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(stzAbs8, 0x9C, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(stzAbs16, 0x9C, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(stzAbsX8, 0x9E, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(stzAbsX16, 0x9E, badOpcode, 1, badOpcode, 3, badOpcode);

    setOpcodes(deca8, 0x3A, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(deca16, 0x3A, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(dex8, 0xCA, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(dex16, 0xCA, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(dey8, 0x88, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(dey16, 0x88, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(inca8, 0x1A, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(inca16, 0x1A, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(inx8, 0xE8, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(inx16, 0xE8, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(iny8, 0xC8, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(iny16, 0xC8, badOpcode, badOpcode, 2, 3, badOpcode);
    // INC group
    setOpcodes(incZp8, 0xE6, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(incZp16, 0xE6, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(incZpX8, 0xF6, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(incZpX16, 0xF6, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(incAbs8, 0xEE, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(incAbs16, 0xEE, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(incAbsX8, 0xFE, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(incAbsX16, 0xFE, badOpcode, 1, badOpcode, 3, badOpcode);
    // DEC group
    setOpcodes(decZp8, 0xC6, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(decZp16, 0xC6, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(decZpX8, 0xD6, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(decZpX16, 0xD6, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(decAbs8, 0xCE, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(decAbs16, 0xCE, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(decAbsX8, 0xDE, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(decAbsX16, 0xDE, badOpcode, 1, badOpcode, 3, badOpcode);
    // AND group
    setOpcodes(andImm8, 0x29, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andImm16, 0x29, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andZp8, 0x25, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andZp16, 0x25, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andZpX8, 0x35, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andZpX16, 0x35, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andSp8, 0x23, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andSp16, 0x23, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andAbs8, 0x2D, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andAbs16, 0x2D, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andAbsX8, 0x3D, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andAbsX16, 0x3D, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andAbsY8, 0x39, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andAbsY16, 0x39, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andLong8, 0x2F, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andLong16, 0x2F, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andLongX8, 0x3F, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andLongX16, 0x3F, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andIndirect8, 0x32, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andIndirect16, 0x32, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andIndirectX8, 0x21, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andIndirectX16, 0x21, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andIndirectY8, 0x31, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andIndirectY16, 0x31, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andIndirectLong8, 0x27, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andIndirectLong16, 0x27, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(andIndirectLongY8, 0x37, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(andIndirectLongY16, 0x37, badOpcode, 1, badOpcode, 3, badOpcode);

    // EOR group
    setOpcodes(eorImm8, 0x49, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorImm16, 0x49, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorZp8, 0x45, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorZp16, 0x45, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorZpX8, 0x55, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorZpX16, 0x55, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorSp8, 0x43, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorSp16, 0x43, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorAbs8, 0x4D, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorAbs16, 0x4D, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorAbsX8, 0x5D, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorAbsX16, 0x5D, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorAbsY8, 0x59, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorAbsY16, 0x59, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorLong8, 0x4F, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorLong16, 0x4F, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorLongX8, 0x5F, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorLongX16, 0x5F, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorIndirect8, 0x52, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorIndirect16, 0x52, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorIndirectX8, 0x41, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorIndirectX16, 0x41, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorIndirectY8, 0x51, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorIndirectY16, 0x51, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorIndirectLong8, 0x47, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorIndirectLong16, 0x47, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(eorIndirectLongY8, 0x57, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(eorIndirectLongY16, 0x57, badOpcode, 1, badOpcode, 3, badOpcode);

    // ORA group
    setOpcodes(oraImm8, 0x09, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraImm16, 0x09, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraZp8, 0x05, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraZp16, 0x05, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraZpX8, 0x15, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraZpX16, 0x15, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraSp8, 0x03, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraSp16, 0x03, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraAbs8, 0x0D, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraAbs16, 0x0D, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraAbsX8, 0x1D, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraAbsX16, 0x1D, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraAbsY8, 0x19, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraAbsY16, 0x19, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraLong8, 0x0F, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraLong16, 0x0F, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraLongX8, 0x1F, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraLongX16, 0x1F, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraIndirect8, 0x12, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraIndirect16, 0x12, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraIndirectX8, 0x01, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraIndirectX16, 0x01, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraIndirectY8, 0x11, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraIndirectY16, 0x11, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraIndirectLong8, 0x07, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraIndirectLong16, 0x07, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(oraIndirectLongY8, 0x17, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(oraIndirectLongY16, 0x17, badOpcode, 1, badOpcode, 3, badOpcode);

    // ADC group
    setOpcodes(adcImm8, 0x69, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcImm16, 0x69, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcZp8, 0x65, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcZp16, 0x65, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcZpX8, 0x75, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcZpX16, 0x75, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcSp8, 0x63, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcSp16, 0x63, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcAbs8, 0x6D, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcAbs16, 0x6D, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcAbsX8, 0x7D, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcAbsX16, 0x7D, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcAbsY8, 0x79, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcAbsY16, 0x79, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcLong8, 0x6F, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcLong16, 0x6F, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcLongX8, 0x7F, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcLongX16, 0x7F, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcIndirect8, 0x72, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcIndirect16, 0x72, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcIndirectX8, 0x61, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcIndirectX16, 0x61, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcIndirectY8, 0x71, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcIndirectY16, 0x71, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcIndirectLong8, 0x67, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcIndirectLong16, 0x67, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(adcIndirectLongY8, 0x77, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(adcIndirectLongY16, 0x77, badOpcode, 1, badOpcode, 3, badOpcode);

    // SBC group
    setOpcodes(sbcImm8, 0xE9, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcImm16, 0xE9, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcZp8, 0xE5, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcZp16, 0xE5, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcZpX8, 0xF5, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcZpX16, 0xF5, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcSp8, 0xE3, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcSp16, 0xE3, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcAbs8, 0xED, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcAbs16, 0xED, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcAbsX8, 0xFD, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcAbsX16, 0xFD, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcAbsY8, 0xF9, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcAbsY16, 0xF9, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcLong8, 0xEF, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcLong16, 0xEF, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcLongX8, 0xFF, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcLongX16, 0xFF, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcIndirect8, 0xF2, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcIndirect16, 0xF2, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcIndirectX8, 0xE1, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcIndirectX16, 0xE1, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcIndirectY8, 0xF1, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcIndirectY16, 0xF1, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcIndirectLong8, 0xE7, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcIndirectLong16, 0xE7, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(sbcIndirectLongY8, 0xF7, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(sbcIndirectLongY16, 0xF7, badOpcode, 1, badOpcode, 3, badOpcode);

    // Transfer group
    setOpcodes(tax8, 0xAA, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(tax16, 0xAA, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(tay8, 0xA8, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(tay16, 0xA8, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(txa8, 0x8A, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(txa16, 0x8A, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(tya8, 0x98, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(tya16, 0x98, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(txy8, 0x9B, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(txy16, 0x9B, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(tyx8, 0xBB, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(tyx16, 0xBB, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(tsx8, 0xBA, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(tsx16, 0xBA, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(txs8, 0x9A, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(txs16, 0x9A, badOpcode, badOpcode, 2, 3, badOpcode);

    // Flag Group
    setOpcodes(clc, 0x18, 0, 1, 2, 3, 4);
    setOpcodes(cld, 0xD8, 0, 1, 2, 3, 4);
    setOpcodes(cli, 0x58, 0, 1, 2, 3, 4);
    setOpcodes(clv, 0xB8, 0, 1, 2, 3, 4);
    setOpcodes(sec, 0x38, 0, 1, 2, 3, 4);
    setOpcodes(sed, 0xF8, 0, 1, 2, 3, 4);
    setOpcodes(sei, 0x78, 0, 1, 2, 3, 4);
    setOpcodes(xce, 0xFB, 0, 1, 2, 3, 4);
    setOpcodes(sep, 0xE2, 0, 1, 2, 3, 4);
    setOpcodes(rep, 0xC2, 0, 1, 2, 3, 4);

    // Stack group
    setOpcodes(phb, 0x8B, 0, 1, 2, 3, badOpcode);
    setOpcodes(phbe, 0x8B, badOpcode, badOpcode, badOpcode, badOpcode, 4);
    setOpcodes(phk, 0x4B, 0, 1, 2, 3, badOpcode);
    setOpcodes(phke, 0x4B, badOpcode, badOpcode, badOpcode, badOpcode, 4);
    setOpcodes(plb, 0xAB, 0, 1, 2, 3, badOpcode);
    setOpcodes(plbe, 0xAB, badOpcode, badOpcode, badOpcode, badOpcode, 4);
    setOpcodes(php, 0x08, 0, 1, 2, 3, 4);
    setOpcodes(plp, 0x28, 0, 1, 2, 3, 4);
    // TODO @IamRifki; Check if this one works better.
    // setOpcodes(php, 0x08, 0, 1, 2, 3, badOpcode);
    // setOpcodes(php, 0x08, 4);
    // setOpcodes(plp, 0x28, 0, 1, 2, 3, badOpcode);
    // setOpcodes(plp, 0x28, 4);
    setOpcodes(pha8, 0x48, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(pha16, 0x48, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(phx8, 0xDA, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(phx16, 0xDA, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(phy8, 0x5A, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(phy16, 0x5A, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(pla8, 0x68, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(pla16, 0x68, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(plx8, 0xFA, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(plx16, 0xFA, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(ply8, 0x7A, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(ply16, 0x7A, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(pei, 0xD4, 0, 1, 2, 3, 4);
    setOpcodes(pea, 0xF4, 0, 1, 2, 3, 4);
    setOpcodes(per, 0x62, 0, 1, 2, 3, 4);
    setOpcodes(phd, 0x0B, 0, 1, 2, 3, 4);
    setOpcodes(pld, 0x2B, 0, 1, 2, 3, 4);

    // CMP group
    setOpcodes(cmpImm8, 0xC9, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpImm16, 0xC9, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpZp8, 0xC5, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpZp16, 0xC5, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpZpX8, 0xD5, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpZpX16, 0xD5, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpSp8, 0xC3, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpSp16, 0xC3, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpAbs8, 0xCD, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpAbs16, 0xCD, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpAbsX8, 0xDD, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpAbsX16, 0xDD, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpAbsY8, 0xD9, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpAbsY16, 0xD9, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpLong8, 0xCF, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpLong16, 0xCF, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpLongX8, 0xDF, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpLongX16, 0xDF, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpIndirect8, 0xD2, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpIndirect16, 0xD2, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpIndirectX8, 0xC1, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpIndirectX16, 0xC1, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpIndirectY8, 0xD1, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpIndirectY16, 0xD1, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpIndirectLong8, 0xC7, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpIndirectLong16, 0xC7, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(cmpIndirectLongY8, 0xD7, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(cmpIndirectLongY16, 0xD7, badOpcode, 1, badOpcode, 3, badOpcode);

    // CPX group
    setOpcodes(cpxImm8, 0xE0, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(cpxImm16, 0xE0, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(cpxZp8, 0xE4, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(cpxZp16, 0xE4, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(cpxAbs8, 0xEC, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(cpxAbs16, 0xEC, badOpcode, badOpcode, 2, 3, badOpcode);

    // CPY group
    setOpcodes(cpyImm8, 0xC0, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(cpyImm16, 0xC0, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(cpyZp8, 0xC4, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(cpyZp16, 0xC4, badOpcode, badOpcode, 2, 3, badOpcode);
    setOpcodes(cpyAbs8, 0xCC, 0, 1, badOpcode, badOpcode, 4);
    setOpcodes(cpyAbs16, 0xCC, badOpcode, badOpcode, 2, 3, badOpcode);

    // Branch group
    setOpcodes(bcc, 0x90, 0, 1, 2, 3, 4);
    setOpcodes(bcs, 0xB0, 0, 1, 2, 3, 4);
    setOpcodes(beq, 0xF0, 0, 1, 2, 3, 4);
    setOpcodes(bne, 0xD0, 0, 1, 2, 3, 4);
    setOpcodes(bra, 0x80, 0, 1, 2, 3, 4);
    setOpcodes(brl, 0x82, 0, 1, 2, 3, 4);
    setOpcodes(bpl, 0x10, 0, 1, 2, 3, 4);
    setOpcodes(bmi, 0x30, 0, 1, 2, 3, 4);
    setOpcodes(bvc, 0x50, 0, 1, 2, 3, 4);
    setOpcodes(bvs, 0x70, 0, 1, 2, 3, 4);

    // Jump group
    setOpcodes(jmp, 0x4C, 0, 1, 2, 3, 4);
    setOpcodes(jmplong, 0x5C, 0, 1, 2, 3, 4);
    setOpcodes(jmpind, 0x6C, 0, 1, 2, 3, 4);
    setOpcodes(jmpindX, 0x7C, 0, 1, 2, 3, 4);
    setOpcodes(jmlind, 0xDC, 0, 1, 2, 3, 4);

    setOpcodes(jsr, 0x20, 0, 1, 2, 3, badOpcode);
    setOpcodes(jsre, 0x20, badOpcode, badOpcode, badOpcode, badOpcode, 4);
    setOpcodes(jsrIndX, 0xFC, 0, 1, 2, 3, badOpcode);
    setOpcodes(jsrIndXE, 0xFC, badOpcode, badOpcode, badOpcode, badOpcode, 4);
    setOpcodes(rts, 0x60, 0, 1, 2, 3, badOpcode);
    setOpcodes(rtsE, 0x60, badOpcode, badOpcode, badOpcode, badOpcode, 4);
    setOpcodes(rtl, 0x6B, 0, 1, 2, 3, badOpcode);
    setOpcodes(rtlE, 0x6B, badOpcode, badOpcode, badOpcode, badOpcode, 4);
    setOpcodes(jsl, 0x22, 0, 1, 2, 3, badOpcode);
    setOpcodes(jslE, 0x22, badOpcode, badOpcode, badOpcode, badOpcode, 4);
    setOpcodes(rti, 0x40, 0, 1, 2, 3, 4);

    // Shift group
    setOpcodes(asla8, 0x0A, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(asla16, 0x0A, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(aslZp8, 0x06, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(aslZp16, 0x06, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(aslZpX8, 0x16, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(aslZpX16, 0x16, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(aslAbs8, 0x0E, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(aslAbs16, 0x0E, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(aslAbsX8, 0x1E, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(aslAbsX16, 0x1E, badOpcode, 1, badOpcode, 3, badOpcode);

    setOpcodes(lsra8, 0x4A, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(lsra16, 0x4A, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(lsrZp8, 0x46, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(lsrZp16, 0x46, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(lsrZpX8, 0x56, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(lsrZpX16, 0x56, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(lsrAbs8, 0x4E, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(lsrAbs16, 0x4E, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(lsrAbsX8, 0x5E, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(lsrAbsX16, 0x5E, badOpcode, 1, badOpcode, 3, badOpcode);

    setOpcodes(rola8, 0x2A, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(rola16, 0x2A, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(rolZp8, 0x26, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(rolZp16, 0x26, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(rolZpX8, 0x36, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(rolZpX16, 0x36, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(rolAbs8, 0x2E, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(rolAbs16, 0x2E, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(rolAbsX8, 0x3E, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(rolAbsX16, 0x3E, badOpcode, 1, badOpcode, 3, badOpcode);

    setOpcodes(rora8, 0x6A, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(rora16, 0x6A, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(rorZp8, 0x66, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(rorZp16, 0x66, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(rorZpX8, 0x76, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(rorZpX16, 0x76, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(rorAbs8, 0x6E, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(rorAbs16, 0x6E, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(rorAbsX8, 0x7E, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(rorAbsX16, 0x7E, badOpcode, 1, badOpcode, 3, badOpcode);

    // BIT group
    setOpcodes(bitImm8, 0x89, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(bitImm16, 0x89, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(bitZp8, 0x24, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(bitZp16, 0x24, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(bitZpX8, 0x34, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(bitZpX16, 0x34, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(bitAbs8, 0x2C, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(bitAbs16, 0x2C, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(bitAbsX8, 0x3C, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(bitAbsX16, 0x3C, badOpcode, 1, badOpcode, 3, badOpcode);

    // Misc group
    setOpcodes(brk, 0x00, 0, 1, 2, 3, 4);
    setOpcodes(xba, 0xEB, 0, 1, 2, 3, 4);
    setOpcodes(nop, 0xEA, 0, 1, 2, 3, 4);
    setOpcodes(tcd, 0x5B, 0, 1, 2, 3, 4);
    setOpcodes(tdc, 0x7B, 0, 1, 2, 3, 4);
    setOpcodes(tcs, 0x1B, 0, 1, 2, 3, 4);
    setOpcodes(tsc, 0x3B, 0, 1, 2, 3, 4);
    setOpcodes(wai, 0xCB, 0, 1, 2, 3, 4);
    setOpcodes(mvp, 0x44, 0, 1, 2, 3, 4);
    setOpcodes(mvn, 0x54, 0, 1, 2, 3, 4);
    setOpcodes(tsbZp8, 0x04, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(tsbZp16, 0x04, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(tsbAbs8, 0x0C, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(tsbAbs16, 0x0C, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(trbZp8, 0x14, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(trbZp16, 0x14, badOpcode, 1, badOpcode, 3, badOpcode);
    setOpcodes(trbAbs8, 0x1C, 0, badOpcode, 2, badOpcode, 4);
    setOpcodes(trbAbs16, 0x1C, badOpcode, 1, badOpcode, 3, badOpcode);
}

pub fn updateCpuMode() void {
    if (p.e != 0) {
        cpuMode = 4;
        x.b.h = 0;
        y.b.h = 0;
    } else {
        cpuMode = 0;
        if (p.m == 0) {
            cpuMode |= 1;
        }
        if (p.x == 0) {
            cpuMode |= 2;
        }
        if (p.x != 0) {
            x.b.h = 0;
            y.b.h = 0;
        }
    }
}
